#ifndef __TIPOS_H__
#define __TIPOS_H__

#include <map>
#include <vector>
#include <fstream>
#include <string.h>
#include <iostream>
#include <ostream>
#include <math.h>
#include <limits.h>
#include <iomanip> //setw, setfill
#include <algorithm>



/******Formato del archivo de datos*******
 * ( TAMANIOS EN BYTE)
 * 
*  CANTIDAD_REGISTRO (1) ( CODIGO_PRODUCTO (5); LONG_MARCA (1) ;  MARCA (255 max); LONG_NOMBRE (1) ; NOMBRE (255 max); LONG_PRES(2) ; PRESENTACION (255 MAX); LONG_PRECIO (1) ; PRECIO (7 MAX) )*
* 
* TAMAÑO DE UN REGISTRO: 1 (cantReg) + 5(cod) + 1 + var + 1 + var + 2 + var + 1 + 7 =
******************************************/

/******Formato del bloque Hoja*******
 * ( TAMANIOS EN BYTE)
 * 
*  CANTIDAD_REGISTRO (1) ; NIVEL (1) ; SIGUIENTE (2) ( CODIGO_PRODUCTO (4) ; NUMERO_BLOQUE (2))*

******************************************/

/******Formato del bloque Nodo*******
 * ( TAMANIOS EN BYTE)
 * 
*  CANTIDAD_REGISTRO (1) ; NIVEL (1) ; SUC_IZQ (2)( CODIGO_PRODUCTO (4)) ; SUC_DER (2))*

******************************************/


using namespace std;
typedef map<int,void *>	 			VectorClaves;
typedef map<int ,void* > 			MapNodo;
typedef map<int ,void* >::iterator	itMapNodo;

#define TAMANIO_BLOQUE_DATO	 	1024//256//128
#define TAMANIO_NODO			512//64//32
#define TAMANIO_LISTA_COD		256//32

#define CANTIDAD_REG_DEFAULT	5000
#define CANT_CODIGOS			20 //cantidad de codigos en la lista de claves secundarias
#define PORCENTAJE_MINIMO		60	//este es el porcentaje de la cantidad total 20%

#define TIPO_DATO_MAX			ULONG_MAX

#define BLOQUE 					TAMANIO_BLOQUE_DATO
#define NODO					TAMANIO_NODO
#define LONG_SEPARA_CAMPOS		1 

#define TAMANIO_PRESENTACION	70 //la que sigue es la maxima posible => NODO - 10 - TAMANIO_PRECIO - 3*LONG_SEPARA_CAMPOS

//2 para los decimales, uno para el punto y el resto prate entera	 
#define TAMANIO_PRECIO 			7 

#define TIPO_DATO					unsigned long //tipo de tamanio del entero
#define TAMANIO_TIPO_DATO			sizeof(TIPO_DATO)
#define TAMANIO_CANTIDAD_REGISTRO	sizeof(char) //los byte que uso para representar la cantidad de registros
#define TAMANIO_NIVEL				sizeof(char) //los byte que uso para representar el tamanio de nivel
#define TAMANIO_SUC_IZQ				sizeof(char)*2
#define TAMANIO_SUC_DER				sizeof(char)*2
#define TAMANIO_COD_PROD			sizeof(TIPO_DATO)
#define TAMANIO_NRO_BLOQ			sizeof(char)*2
#define TAMANIO_BYTE_DIN			sizeof(char)//numero con el cual se indica el largo del string como por ejemplo la marca
#define TAMANIO_BYTE_PRES			sizeof(char)*2//numero con el cual se indica el largo del string como por ejemplo la marca
#define TAMANIO_BYTE_LISTA			sizeof(char) //cantidad de byte que se usa para contar la contidad de item de la lista en el archivo de lista de codigos

#define TAMANIO_NOMBRE			128 //nombre del producto
#define TAMANIO_MARCA 			128 //marca del producto
#define TAMANIO_CLAVE 			128 //nombre o marca de la clave secundaria


#define PATH_ARCH_INDICE  				"" //archivo donde se guardan los nodos del arbol
#define EXT_ARCH_INDICE					".idc" 

#define PATH_ARCH_ESPACIO  				"" //archivo donde se guardan los nodos del arbol
#define EXT_ARCH_ESPACIO				".esp" 

//#define NOM_ARCH_INDICE_PRIM			"indicePrimario" //archivo donde se guardan los nodos del arbol
#define NOM_ARCH_INDICE_PRIM		 PATH_ARCH_INDICE + "idxPrimario" + EXT_ARCH_INDICE
#define NOM_ARCH_INDICE_CAND		 PATH_ARCH_INDICE + "idxCandidato" + EXT_ARCH_INDICE
#define NOM_ARCH_INDICE_SEC_MARC	 PATH_ARCH_INDICE + "idxSecMarca" + EXT_ARCH_INDICE
#define NOM_ARCH_INDICE_SEC_NOM		 PATH_ARCH_INDICE + "idxSecNombre" + EXT_ARCH_INDICE

#define NOM_ARCH_INDICE_SEC_MARC_SEC	 PATH_ARCH_INDICE + "idxSecMarcaSec" + EXT_ARCH_INDICE
#define NOM_ARCH_INDICE_SEC_NOM_SEC		 PATH_ARCH_INDICE + "idxSecNombreSec" + EXT_ARCH_INDICE

#define NOM_ARCH_ESPACIO_PRIM		 PATH_ARCH_ESPACIO + "Primario" + EXT_ARCH_ESPACIO
#define NOM_ARCH_ESPACIO_CAND		 PATH_ARCH_ESPACIO + "Candidato" + EXT_ARCH_ESPACIO
#define NOM_ARCH_ESPACIO_SEC_MARC	 PATH_ARCH_ESPACIO + "SecMarca" + EXT_ARCH_ESPACIO
#define NOM_ARCH_ESPACIO_SEC_NOM	 PATH_ARCH_ESPACIO + "SecNombre" + EXT_ARCH_ESPACIO
#define NOM_ARCH_ESPACIO_DATOS		 PATH_ARCH_ESPACIO + "Datos" + EXT_ARCH_ESPACIO
#define NOM_ARCH_ESPSEC_DATOS		 PATH_ARCH_ESPACIO + "DatosSec" + EXT_ARCH_ESPACIO



#define PATH_ARCH_DATO  		"" //archivo donde se guardan los nodos del arbol
#define EXT_ARCH_DATO			".dat" 

#define NOM_ARCH_DATO			PATH_ARCH_DATO + "Datos" +EXT_ARCH_DATO //archivo donde se guardan los nodos del arbol

#define NOM_ARCH_SALIDA			PATH_ARCH_DATO + "Informe" +EXT_ARCH_DATO //archivo donde se guardan los nodos del arbol

#define TIPO_DATO_MAX			ULONG_MAX
#define FIN_SET_SECUENCIAL		0 //se usa el maximo valor que soporta TIPO_DATO/*B+*/

#define TIPO_DATO_CHICO			int //usado para la profundidad del arbol


#define TAMANIO_HOJA_TOTAL		255
#define TAMANIO_NODO_TOTAL		255



/*MACROS*/

//#define CLAVE_SEC_NOMBRE			0x0000L
#define CLAVE_SEC_MARCA				0x0001L
#define CLAVE_CANDIDATA				0x0002L
#define CLAVE_PRIMARIA				0x0004L
#define CLAVE_SEC_NOMBRE			0x0008L



struct SortDesc
{
     bool operator()(TIPO_DATO rpStart, TIPO_DATO rpEnd)
     {
          return (rpStart) > (rpEnd);
     }
};


/*-----------------------------------------------------------*/
void reverse(char s[]){
	int c,i,j;
	for(i=0,j=(int)strlen(s)-1; i<j; i++, j-- ){
		c=s[i];
		s[i]=s[j];
		s[j]=c;
	}
}
/*-----------------------------------------------------------*/
string itoa(int n)
{
	int i,sign;
	string numero;
	char s[10];
	if ( (sign=n) < 0 ) //registra el signo
		n=-n;			//vuelve a n positivo
	i=0;
	do{	//genera digitos en orden inverso
		s[i++] = n % 10 + '0'; 	//toma el siguiente digito	
	}while ((n/=10) >0);	//b�rralo
	if(sign<0)
		s[i++]='-';
	s[i]='\0';
	reverse(s);
	return numero.append(s);
}
/*-----------------------------------------------------------*/
bool isNumero(char* numero)
{
	unsigned int i=0;
	while(i < strlen(numero))
	{
		if(!isdigit((int)numero[i]))
			return false;	
		++i;		
	}
	return true;
}
/*-----------------------------------------------------------*/
/*Lo usamos cuando transformamos de un entero a cierta cantidad de char*/
/*REMPLAZO DE ITOA*//*es el formato de las longitudes*/
string convertirChar(TIPO_DATO dato,int cantByte)
{
	string aux="";
//	char carAux[1]={};
//	carAux[0] = '0';
//	carAux[1] = '\0';
	unsigned char charAux[1]={};
	int resultado,resto,contador=0,i=0;
	if(cantByte>1)
	{
		resultado = dato/255;
		if(resultado>0)
			contador = (int)log10((double)resultado) + 1;
		//cargo los ceros que van adelante si lo tiene
		while(i<((cantByte-1)-(contador)))
		{
			aux.append("0");
			++i;
		}
		if(resultado!=0)
			aux+=itoa(resultado);
	}
	resto = dato%255;
	charAux[0] = (unsigned char)(resto+1);
	//charAux[1] = '\0';
	aux+=charAux[0];
	return aux;
}
/*-----------------------------------------------------------*/
/*a partir de la cadena de caracteres obtengo el tipo dato*/
TIPO_DATO string2TipoDato(string dato)
{
	TIPO_DATO tamanio=0;
	string strNumero="",strResto="";
	int numero=0,resto=0;

	tamanio = (int)dato.length();
	if(tamanio>1)
	{
		strNumero = dato.substr(0,tamanio-1);

		numero = atoi(strNumero.c_str());
		numero *= 255;
	}	

	strResto = dato[tamanio-1];	
	//esto es por que el resto es solo un byte.
	resto = (unsigned int)((unsigned char)strResto.c_str()[0]);
	return (TIPO_DATO)(numero + resto-1);


}
#include "ClavePrimaria.h"
#include "ClaveCandidata.h"
#include "ClaveSecundaria.h"
#include "ClaveEspacioLibre.h"
#include "ClaveSecundariaSec.h"

#endif /*TIPOS_H_*/
